package com.cycrix.sensor;

import java.io.IOException;
import java.net.Socket;
import java.util.List;

import android.app.Activity;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

import com.cycrix.tcp.TcpAccelerometer;
import com.cycrix.tcp.TcpConnection;
import com.cycrix.tcp.TcpObject;
import com.cycrix.tcp.TcpServer;
import com.cycrix.tcp.TcpText;

public class AccelerometerActivity extends Activity implements SensorEventListener {
	
	private SensorManager mSensorManager;
    private List<Sensor> mSensorList;
    private Button _btnSend;
    private TextView _txtOutput;
    
    private TcpServer _server;
	private TcpConnection _con;
    
	@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.accelerometer_screen);
        
        _txtOutput = (TextView) findViewById(R.id.txtOutput);
        _btnSend = (Button) findViewById(R.id.btnSend);
        _btnSend.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				
			}
		});
        
        mSensorManager = 
        		(SensorManager) getSystemService(Context.SENSOR_SERVICE);
        mSensorList = mSensorManager.getSensorList(Sensor.TYPE_ACCELEROMETER);
        
        StringBuilder buildler = new StringBuilder();
        for (Sensor sensor : mSensorList) {
        	buildler.append("Name: ").append(sensor.getName())
        	.append("\n");
        	buildler.append("Vendor: ").append(sensor.getVendor())
        	.append("\n");
        	buildler.append("Version: ").append(sensor.getVersion())
        	.append("\n");
        	buildler.append("Power: ").append(sensor.getPower())
        	.append(" mA\n");
        	buildler.append("MinDelay: ").append(sensor.getMinDelay())
        	.append(" us\n");
        	buildler.append("Resolution: ").append(sensor.getResolution())
        	.append("\n");
        	buildler.append("MaxRange: ").append(sensor.getMaximumRange())
        	.append("\n");
        	buildler.append("\n");
        }
        
        //((TextView) findViewById(R.id.txtType)).setText(buildler.toString());
        
        Sensor sensor = mSensorList.get(0);
        mSensorManager.registerListener(this, mSensorList.get(0),
        		SensorManager.SENSOR_DELAY_FASTEST);
        
        try {
			_server = new TcpServer(12345, new  Handler() {
				@Override
				public void handleMessage(Message msg) {
					switch (msg.what) {
					case TcpServer.DID_ACCEPT:
						ServerAccecpt(msg);
						break;
						
					case TcpServer.DID_ERROR:
						println("<<<serve error>>>");
						break;
					}
				}
			});
		} catch (IOException e) {
			finish();
		}
    }
	
	private void ServerAccecpt(Message msg)
	{
		try {
			if (_con != null)
				_con.close();

			_con = new TcpConnection((Socket) msg.obj, new Handler() {
				public void handleMessage(Message msg) {
					switch (msg.what) {
					case TcpConnection.DID_RECEIVE:
						HandleRecv((TcpObject) msg.obj);
						break;
					case TcpConnection.DID_CLOSE:
						println("<<<connection closed>>>");
						break;
					case TcpConnection.DID_ERROR:
						println("<<<connection error>>>");
						break;
					}
				}
			});

			println("<<<Connection accepted" + 
					_con._socket.getRemoteSocketAddress().toString() + ">>>");
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	private void HandleRecv(TcpObject tcpObj) {
		switch (tcpObj.GetType()) {
		case TcpConnection.ENUM_TEXT:
			println(((TcpText) tcpObj).GetText());
			break;
		}
	}
	
	@Override
	protected void onResume() {		
		super.onResume();
	}
	
	@Override
	protected void onPause() {
		super.onPause();
	}
	
	@Override
	protected void onDestroy() {
		super.onDestroy();
		mSensorManager.unregisterListener(this, mSensorList.get(0));
	}

	public void onAccuracyChanged(Sensor sensor, int accuracy) {
		
	}

	private long _timeStamp = 0;
	private long _count = 1;
	private final long _interval = 500 * 1000000;
	public void onSensorChanged(SensorEvent event) {
		if (event.timestamp - _timeStamp > _interval) {
			String FPS = "FPS: " + 
					Long.toString(_count * 1000000000 / _interval);
			((TextView) findViewById(R.id.txtFPS)).setText(FPS);
			Log.d("AccelerometerActivity", FPS);
			((TextView) findViewById(R.id.txtInterval))
			.setText("Interval: " + 
					Long.toString(_interval / (_count * 1000000)) + " ms");
			((TextView) findViewById(R.id.txtX)).setText("X: " + 
					Float.toString(event.values[0]) + " m/s^2");
			((TextView) findViewById(R.id.txtY)).setText("Y: " + 
					Float.toString(event.values[1]) + " m/s^2");
			((TextView) findViewById(R.id.txtZ)).setText("Z: " +
					Float.toString(event.values[2]) + " m/s^2");
			double magnitude = 0;
			for (int i = 0; i < 3; i++) {
				magnitude += event.values[i] * event.values[i];
			}
			magnitude = Math.sqrt(magnitude);
			((TextView) findViewById(R.id.txtMagnitude)).setText("Mag: " +
					Double.toString(magnitude) + " m/s^2");
			_count = 0;
			_timeStamp = event.timestamp;
		}
		if (_con != null && _con._socket.isConnected()){
			try {
				_con.send(new TcpAccelerometer(event.values[0], 
						event.values[1], event.values[2]));
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
		_count++;
	}
	
	private void println(String s) {
		CharSequence origin = _txtOutput.getText();
		System.currentTimeMillis();
		_txtOutput.setText(s + "\n" + origin);
	}
}